<script setup lang="ts">
import ComponentsPhone from '@/components/ComponentsPhone.vue';
import { ref, onMounted, onUnmounted } from 'vue';
import { NGrid, NGridItem, NFlex, NCard, NButton, NDrawer, NDrawerContent, NFormItem, NIcon, NTimePicker, NDatePicker, NTree, createDiscreteApi, NResult, c } from 'naive-ui';
import { sseService } from "@/assets/utils/sse";
import type { SSEChatParams } from "@/assets/utils/sse";
import { GET_ORGN, ADD_MEET } from "@/service/apis/meet";
import SvgIcon from '@/components/SvgIcon.vue'
import { sseUrl } from "@/service/sseUrl";
import Papa from "papaparse";
import { useCounterStore } from '@/stores/counter'
import { SrsRtcPublisherAsync, SrsRtcPlayerAsync } from '../assets/utils/webrtc'


const { message } = createDiscreteApi(["message"])
const tokenStore = useCounterStore()
const mailShow = ref(false);
const contentRef = ref<any>(null)

/**
 * 通过事件监听来确定是预约通话还是拨打电话
 * @param payload 
 */
const showMail = (payload: any) => {
    mailShow.value = true;
    if (payload === '预约通话') {
        flag.value = '预定'
    } else if (payload === '拨打电话') {
        flag.value = '呼叫'
    }
}

const flag = ref('预定')
//人员组织数据
const treeData: any = ref([])
const loading = ref(false)

const meetList = ref<any>([]);  //通话列表
const meetListSelect = ref<any>([]); //通话的人员
const PmianVideoRef = ref<any>(null)

const meetingId = ref() //通话ID

// callerList 定义电话信息接口
const callerList = ref({
    time: null,
    date: null,
    person: []

})
const sdk_push: any = ref(null)//推流
const sdk_pull: any = ref(null)//拉流
// 定义可视电话面板状态是否显示
const phoneShow = ref(false);

/**
 * 接听电话函数 传递那个电话
 * @param val 
 */
const openPhoneDrawer = (val: any) => {
    console.log('接听的电话数据值：', val);

    meetingId.value = val.id

    phoneShow.value = true;
    let arr = val.人员

    meetListSelect.value = []
    for (let inde1x = 0; inde1x < arr.length; inde1x++) {
        const element = arr[inde1x];
        if (element['工号'] == tokenStore.info['工号']) {
            meetListSelect.value.splice(0, 0, element)
        } else {
            meetListSelect.value.push(element)
        }
    }

    console.log('当前电话的通话人员：', meetListSelect.value);
    const tempPerson = meetListSelect.value

    setTimeout(() => {
        let ele = PmianVideoRef.value
        for (let index = 0; index < ele.length; index++) {
            const element = ele[index];
            if (index == 0) {
                sdk_push.value = SrsRtcPublisherAsync();
                let url = tempPerson[0]['流地址'];
                element.srcObject = sdk_push.value.stream
                console.log('推流地址', url)

                sdk_push.value.publish(url).then(function (session: any) {
                    console.log('推流成功', session)
                }).catch(function (reason: any) {
                    console.log('推流失败', reason)
                    sdk_push.value.close();
                });
            }
            if (index > 0) {
                sdk_pull.value = SrsRtcPlayerAsync();
                element.srcObject = sdk_pull.value.stream
                let url = tempPerson[index]['流地址'];;
                sdk_pull.value.play(url).then(function (session: any) {
                }).catch(function (reason: any) {
                    sdk_pull.value.close();
                });
            }
        }
    }, 2000)
}

onMounted(() => {
    //构建SSE连接
    sseServiceOpen()
    //加载通讯录
    getOrgin()
})
onUnmounted(() => {
    sseService.disconnect()
})

//see 链接
const sseServiceOpen = () => {
    const onopen = () => {
        console.log("建立会议列表sse连接成功")
    }
    // 建立连接
    let sseChatParams: SSEChatParams = {
        onopen,
        url: sseUrl.video,
        onmessage: (event: MessageEvent) => {
            // 收到消息
            console.log('SSE推送的可视电话数据：', event.data);
            let fst = event.data.replace(/\\n/g, "\n")
            let strArr = fst.split('\n')
            let strArr1 = strArr[0].split('\n')
            console.log('转换后的SSE推送的可视电话数据：', Papa.parse(fst, { header: true, delimiter: ";", newline: "\n" }), strArr, strArr1);
            // debugger
            const phoneData: any = Papa.parse(fst, { header: true, delimiter: ";", newline: "\n" })
            console.log('转换后的csv数据json：', phoneData);

            //获取全部的电话数据 phoneData
            if (phoneData.data.length < 1)
                return;
            const closePhone = phoneData.data.map((item: any) => {
                if (item.类型 === '取消') {
                    meetList.value.forEach((el: any, inedx: any) => {
                        if (item.id == el.id) {
                            meetList.value.splice(inedx, 1)
                        }
                    })
                    return item;
                } else if (item.类型 !== '取消') {
                    return item;
                }
            })
            console.log('挂断的电话数据：', closePhone);
            const tempData = phoneData.data.filter((item: any) =>
                item.类型 !== '取消').map((item: any) => {
                    item.人员 = JSON.parse(item.人员);
                    return item;
                })

            meetList.value = meetList.value.concat(tempData)
            console.log('当前电话列表：', meetList.value);
            /**
             * 只有没有通话的情况下，才可以接听拨打的电话 phoneShow.value == false
             * 当自己创建的拨打电话时，类型是呼叫的没有问题？
             * 存在的问题是，当他人创建的拨打电话，类型也是呼叫到当前用户时，就会出现多个电话列表。
             * 解决方式，以当前用户为准，优先接听。当没有自己创建的时候，按照时间排序，接听最早的电话
             */
            if ( phoneShow.value == false && phoneData.data.length > 0 && phoneData.data[0]['类型'] == '呼叫') {
                console.log('直拨的电话：',phoneData.data)
                phoneData.data.forEach((item:any)=>{
                    const tem =item.人员
                    const temIndex = tem.findIndex((item2:any)=>{
                        if(item2['工号'] == tokenStore.info['工号']){
                            console.log('找到自己的信息',item)
                            meetListSelect.value = item
                            openPhoneDrawer(item)
                            return true;
                        }
                    })
                    console.log('找到自己的信息',temIndex)
                    if(temIndex === -1){

                        meetListSelect.value = phoneData.data[0]
                        openPhoneDrawer(phoneData.data[0])
                    }
                })
                
            }

        },
        finallyHandler: () => {
            console.log("finallyHandler操作")
        }
    };
    sseService.connect(sseChatParams)
}
/**
 * 对选择通话人员做限制人数
 */
const tempCheckedKeys = ref([])
const updateCheckedKeys = (a: any, b: any) => {
    
    const bArr = b.slice(0, 4);
    tempCheckedKeys.value = a
    if (a.length > 3) {
        tempCheckedKeys.value = []
        message.error('只能选3人通话')
        return
    } else {
        callerList.value.person = bArr
    }
}

/**
 * 初始化通讯录
 */
const getOrgin = () => {
    GET_ORGN().then((res: any) => {
        recursionRemoveEmpty(res.data)
    }).catch((err) => {
        console.log(err);
    })
}

/**
 * 预约电话
 */
const addMeets = () => {
    loading.value = true
    if (callerList.value.date == null || callerList.value.time == null || callerList.value.person.length == 0) {
        message.error('请选择数据后在提交')
        loading.value = false
    } else {
        let p: any = {
            类型: '数据',
            内容: {
                应用名称: "我的电话",
                类型: '预约',
                时间: `${callerList.value.date} ${callerList.value.time}`,
                人员: callerList.value.person
            }
        }
        ADD_MEET({ params: JSON.stringify(p) }).then((res: any) => {
            if (res.stacode == 200) {
                loading.value = false
                reset()
                mailShow.value = false
                message.success(res.message)
            }
        }).catch((err) => {
            console.log(err);
            loading.value = false
        })
    }
}
/**
 * 清空通讯录选中项
 */

const reset = () => {
    callerList.value.date = null
    callerList.value.time = null
    callerList.value.person = []
    tempCheckedKeys.value = []
    console.log('清空通讯录选中项', callerList.value);
}
/**
 * 直拨电话
 */
const callMeet = () => {
    
    if (callerList.value.person.length == 0) {
        message.error('请选择数据后在提交')
        loading.value = false
    } else {
        let p: any = {
            类型: '数据',
            内容: {
                应用名称: "我的电话",
                类型: '呼叫',
                人员: callerList.value.person
            }
        }
        ADD_MEET({ params: JSON.stringify(p) }).then((res: any) => {
            if (res.stacode == 200) {
                reset()
                
            }
        }).catch((err) => {
            console.log(err);
            // loading.value = false
        })
    }

    setTimeout(() => {
        callmeetNT()
    }, 1000)
}
/**
 * 直拨电话跳转到通话窗口
 */
 const callmeetNT = () => {
    reset()
    loading.value = false
    mailShow.value = false
}

/**
 * 通讯录结构
 * @param data 
 */
const recursionRemoveEmpty = (data: any) => {
    data = data.filter((item: any) => {
        if (item.children) item.children = recursionRemoveEmpty(item.children);
        if (item.children && item.children.length === 0) delete item.children;
        return item;
    });
    return treeData.value = data;
}


/**
 * 通话挂断
 * @param val 
 * @param data 
 */
const cancelMeet = (val: string, data: any) => {
    // debugger;
    console.log('挂断电话的参数：', data, val);

    loading.value = true

    let p: any = {
        类型: "数据",
        内容: {
            应用名称: "我的电话",
            meetId: data.id,
            类型: val,
        }
    }
    ADD_MEET({ params: JSON.stringify(p) }).then((res: any) => {
        if (res.stacode == 200) {
            loading.value = false
            
        }
    }).catch((err) => {
        console.log(err);
        loading.value = false
    })

    sdk_push.value.close();
    sdk_pull.value.close();
}

//挂断电话
const cancelPhone = (num: number) => {
    loading.value = true
    let p: any = {
        类型: "数据",
        内容: {
            应用名称: "我的电话",
            token: tokenStore.token,
            类型: '取消',
            meetId: meetingId.value
        }
    }

    ADD_MEET({ params: JSON.stringify(p) }).then((res: any) => {
        phoneShow.value = false
        loading.value = false
    }).catch((err) => {
        console.log(err);
    })

    sdk_push.value.close();
    sdk_pull.value.close();
}

/**
 * 只能选择比当前时间晚的日期
 */
const disablePreviousDate = (ts: number) => {

    return ts < Date.now() - 86400000;
}
const isHourDisabled = (hour: number) => {
    const now = new Date();
    const day = now.toISOString().split('T')[0]
    console.log('日期', callerList.value.date,)
    if (day === callerList.value.date) {
        const hourNow = now.getHours();
        return hour < hourNow;
    }
    return hour < 0;
}
/**
 * 限制时间的相关函数结束
 */
</script>
<template>

    <ComponentsPhone title="我的电话" icon="shipinhuiyi" @show-mail="showMail">
        <template #default>
            <!-- 这是电话列表 -->
            <div id="drawer-mail">
                <n-grid v-if="meetList.length > 0" :x-gap="8" :y-gap="8" :cols="6">
                    <n-grid-item v-for="(item, index) in meetList" :key="index">
                        <n-card :title="item['人员'][0]['姓名']">
                            <template #header-extra>
                                <!-- 图标 {{tokenStore.info['工号']}} -->
                                <n-icon :size="40">
                                    <svg-icon v-if="tokenStore.info['工号'] == item['人员'][0]['工号']"
                                        iconClass="phone-call-forward" />
                                    <svg-icon v-else iconClass="phone-call-incoming" />
                                </n-icon>
                            </template>
                            <template #default>
                                <div>{{ item.时间 }}</div>
                                <n-grid :x-gap="8" :y-gap="8" :cols="2">
                                    <template v-for="(m, n) in item['人员']" :key="n">
                                        <n-grid-item v-if="m.姓名 != item['人员'][0]['姓名']">
                                            <div v-if="n < 4">{{ m.姓名 }}</div>
                                        </n-grid-item>
                                    </template>
                                </n-grid>
                            </template>
                            <template #action>
                                <n-flex justify="space-around">
                                    <n-button @click="openPhoneDrawer(item)" type="primary" size="small">接听</n-button>
                                    <n-button type="error" size="small" @click="cancelMeet('取消', item)">挂断</n-button>
                                </n-flex>
                            </template>
                        </n-card>
                    </n-grid-item>
                </n-grid>
                <n-grid v-else :x-gap="1" :y-gap="1" :cols="1">
                    <n-grid-item>
                        <n-card
                            style="padding: 10%;justify-content: center;align-items: center;height: calc(100vh - 223.35px);">
                            <n-result title="暂无可视电话" size="huge">
                                <template #icon>
                                    <svg-icon iconClass="dianhua1" className="icon2" />
                                </template>
                            </n-result>
                        </n-card>
                    </n-grid-item>
                </n-grid>
            </div>
            <!-- 这是电话列表结束 -->
            <!-- 这是拨打电话面板 -->
            <n-drawer v-model:show="mailShow" width="30%" placement="left" :trap-focus="false" :block-scroll="false"
                :show-mask="false" to="#drawer-mail">
                <n-drawer-content title="通讯录" closable>

                    <n-form-item v-if="flag == '预定'" label-placement="left" label="通话时间">
                        <n-date-picker size="small" clearable type="date" v-model:formatted-value="callerList.date"
                            value-format="yyyy-MM-dd" :actions="['now']" style="margin-right: 10px;"
                            :is-date-disabled="disablePreviousDate" />
                        <n-time-picker size="small" clearable v-model:formatted-value="callerList.time"
                            value-format="HH:mm:ss" :is-hour-disabled="isHourDisabled" />
                    </n-form-item>
                    <n-form-item label-placement="left" label="通讯录">
                        <n-tree block-line cascade checkable :selectable="false" :show-line="true" :data="treeData"
                            key-field="id" label-field="label" children-field="children" virtual-scroll
                            style="height: 100%" @update:checked-keys="updateCheckedKeys" check-strategy="child"
                            :checked-keys="tempCheckedKeys" />
                    </n-form-item>
                    <template #footer>
                        <div style="display: flex;flex-direction: row;justify-content: right; ">
                            <n-button v-if="flag == '预定'" type="primary" size='small' @click="addMeets"
                                :loading="loading">保存</n-button>
                            <n-button v-if="flag == '呼叫'" type="primary" size='small' @click="callMeet"
                                :loading="loading">拨打</n-button>
                            <n-button type="warning" size='small' style="margin-left: 10px;"
                                @click="reset">取消</n-button>
                        </div>
                    </template>
                </n-drawer-content>
            </n-drawer>
            <!-- 这是拨打电话面板结束 -->
        </template>
    </ComponentsPhone>
    <!-- 这是视频通话面板 -->
    <n-drawer ref="drawerRightRef" v-model:show="phoneShow" width="100%" placement="right" :trap-focus="false"
        :block-scroll="false" :mask-closable="false" :show-mask="false" to="#drawer-mail">
        <n-drawer-content title="视频通话" closable ref="contentRef" id="contentRef">
            <n-grid :x-gap="2" :cols="2">
                <template v-for="(item, index) in meetListSelect" :key="index">
                    <n-grid-item>
                        <n-card :title="item.姓名" style="height: 100%;">
                            <video class="mian_video" controls autoplay ref="PmianVideoRef"></video>
                            <template #action v-if="index == 0">
                                <n-flex justify="center">
                                    <n-button type="error" circle size="large" @click="cancelPhone(0)">挂断</n-button>
                                </n-flex>
                            </template>
                        </n-card>
                    </n-grid-item>
                </template>

            </n-grid>

        </n-drawer-content>
    </n-drawer>
    <!-- 这是视频通话面板结束 -->
</template>
<style scoped>
.mian_video {
    height: 100%;
    width: 100%;
    border-radius: 10px;
    object-fit: cover;
}

.icon {
    height: 2em;
    width: 2em;
}

.icon2 {
    height: 4em;
    width: 4em;
}
</style>